package dev.ece.suit.loader.models.fbx;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;

import dev.ece.util.lib.Vector3f;

public class FBXAnimationCurveNode {

	public static final String ANIMATION_CURVE_NODE = "AnimationCurveNode";
	
	private long id;
	
	private String type;
	
	private Vector3f p = new Vector3f();
	
	private List<FBXAnimationCurve> curves = new ArrayList<FBXAnimationCurve>();
	
	public Vector3f toLoalTransform(long fbx_time) {
		Vector3f vector = new Vector3f(p);
		float[] result = vector.getVector();
		int index = 0;
		for(FBXAnimationCurve curve: curves) {
			result[index ++] = curve.interpolate(fbx_time);
		}
		float temp = result[1];
		result[1] = result[2];
		result[2] = temp;
		return vector;
	}
	
	public static FBXAnimationCurveNode[] parseFBXAnimationCurveNode(List<FBXElement> elements) {
		if(elements != null && !elements.isEmpty()) {
			FBXAnimationCurveNode[] nodes = new FBXAnimationCurveNode[elements.size()];
			FBXElement element = null;
			FBXElement child = null;
			Map<String, Float> coord = null;
			for(int i=0; i<nodes.length; i++) {
				nodes[i] = new FBXAnimationCurveNode();
				element = elements.get(i);
				nodes[i].id = (Long) element.getProperties()[0].getValue();
				child = element.findFirstChild(FBXModelLoader.PROPERTIES70);
				coord = toCoord(child.findChildren(FBXModelLoader.P));
				nodes[i].p.set(coord.get("X"), coord.get("Y"), coord.get("Z"));
				nodes[i].type = (String) element.getProperties()[1].getValue();
			}
			return nodes;
		}
		return null;
	}
	
	public static Map<String, Float> toCoord(FBXElement[] p) {
		Map<String, Float> coord = new ConcurrentHashMap<String, Float>();
		if(p != null) {
			String type = null;
			String[] types = null;
			Float value = null;
			for(FBXElement element: p) {
				type = (String) element.getProperties()[0].getValue();
				types = StringUtils.split(type, "|");
				if(StringUtils.equals(types[0], "d")) {
					value = ((Double) element.getProperties()[4].getValue()).floatValue();
				} else if(StringUtils.equals(types[0], "f")) {
					value = (Float) element.getProperties()[4].getValue();
				}
				coord.put(StringUtils.upperCase(types[1]), value.isNaN() ? 0 : value);
			}
		}
		return coord;
	}
	
	public static void connectToFBXModel(Map<Long, List<FBXConnection>> connections, FBXAnimationCurveNode[] nodes, FBXModel[] models) {
		if(nodes != null) {
			Map<Long, FBXModel> modelmap = FBXModel.toFBXModelMap(models);
			List<FBXConnection> conns = null;
			FBXModel model = null;
			for(FBXAnimationCurveNode node: nodes) {
				conns = connections.get(node.getId());
				if(conns != null) {
					for(FBXConnection conn: conns) {
						model = modelmap.get(conn.getTo());
						if(model != null) {
							if(StringUtils.equals("T", node.getType())) {
								model.setTranslation(node);
							} else if(StringUtils.equals("R", node.getType())) {
								model.setRotation(node);
							} else if(StringUtils.equals("S", node.getType())) {
								model.setScaling(node);
							}
						}
					}
				}
			}
		}
	}
	
	public static Map<Long, FBXAnimationCurveNode> toFBXAnimationCurveNodeMap(FBXAnimationCurveNode[] nodes) {
		Map<Long, FBXAnimationCurveNode> map = new ConcurrentHashMap<Long, FBXAnimationCurveNode>();
		if(nodes != null) {
			for(FBXAnimationCurveNode node: nodes) {
				map.put(node.getId(), node);
			}
		}
		return map;
	}

	public long getId() {
		return id;
	}

	public Vector3f getP() {
		return p;
	}

	public String getType() {
		return type;
	}

	public List<FBXAnimationCurve> getCurves() {
		return curves;
	}
	
}
